package componentes.basicos;

/**
 * Classe que representa uma unidade de controle para a ALU. Essa classe
 * permite definir os sinais de controle que podem ser enviados para a ALU.
 * 
 * @author Gustavo Miguel, Cleisson Alves, Evandro Francisco, Lucas.
 */
public class ControleALU {
    
    /* Atributos da classe */
    private Barramento funct;
    private Barramento opALU;
    private Barramento saida;
    
    /**
     * Construtor da classe, cria uma unidade de controle padrão. Uma unidade
     * de controle padrão possui todas as suas entradas e saída inoperantes.
     * @see Constantes.
     * @see Barramento.
     * @see ALU.
     */
    public ControleALU() {
        this.funct = new Barramento(Constantes.INOPERANTE);
        this.opALU = new Barramento(Constantes.INOPERANTE);
        this.saida = new Barramento(Constantes.INOPERANTE);
    }

    /**
     * Retorna o Barramento correspondente a função passada para ALU.
     * @return Barramento que corresponde a função.
     */
    public Barramento getFunct() {
        return funct;
    }

    /**
     * Retorna o Barramento correspondente ao sinal de operação enviado para ALU.
     * @return Barramento que corresponde ao sinal de operação resultante.
     */
    public Barramento getOpALU() {
        return opALU;
    }

    /**
     * 
     * Retorna o Barramento correspondente ao sinal de operação enviado para ALU.
     * @return Barramento que corresponde ao sinal de operação resultante.
     */
    public Barramento getSaida() {
        return saida;
    }

    /**
     * Configura o Barramento de função de controle da unidade de controle.
     * @param funct Barramento de função.
     */
    public void setFunct(Barramento funct) {
        this.funct = funct;
    }

    /**
     * Configura o Barramento de sinal de operação.
     * @param opALU Barramento correspondente ao sinal de operação.
     */
    public void setOpALU(Barramento opALU) {
        this.opALU = opALU;
    }

    /**
     * Método para configurar o Barramento de saida da unidade de controle
     * de acordo com OpALU e funct.
     */
    public void setSaida() {
        if(opALU.getSubBitsValor(30, 32) == 1) {
            this.saida.setBits(Constantes.SUB);
        } else if(opALU.getSubBitsValor(30, 32) == 0) {
            this.saida.setBits(Constantes.ADD);
        } else if(funct.getBits().endsWith("100000")) {
            this.saida.setBits(Constantes.ADD);
        } else if(funct.getBits().endsWith("100010")) {
            this.saida.setBits(Constantes.SUB);
        } else if(funct.getBits().endsWith("100100")) {
            this.saida.setBits(Constantes.AND);
        } else if(funct.getBits().endsWith("100101")) {
            this.saida.setBits(Constantes.OR);
        } else if(funct.getBits().endsWith("101010")) {
            this.saida.setBits(Constantes.SLT);
        } else {
            this.saida.setBits(Constantes.ADD);
        }
    }
    
} // Fim da classe.
